package com.bwie.auth.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.bwie.auth.feign.UserLoginFeign;
import com.bwie.auth.service.UserLoginService;
import com.bwie.common.constants.JwtConstants;
import com.bwie.common.constants.TokenConstants;
import com.bwie.common.domain.TUser;
import com.bwie.common.domain.dto.ForgetPasswordDto;
import com.bwie.common.domain.dto.UserInfoReq;
import com.bwie.common.domain.dto.UserLoginRequest;
import com.bwie.common.domain.dto.UserRegisteredReq;
import com.bwie.common.domain.vo.JwtResponse;
import com.bwie.common.result.Result;
import com.bwie.common.sms.SendSmsUtils;
import com.bwie.common.utils.JwtUtils;
import com.bwie.common.utils.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author zt181
 * @date 2025/7/15
 */

@Service
public class UserLoginServiceImpl implements UserLoginService {

    @Resource
    private UserLoginFeign userLoginFeign;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private SendSmsUtils sendSmsUtils;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public Result<TUser> login(UserLoginRequest userLoginRequest) {
        // 校验参数
        if (ObjectUtil.isNull(userLoginRequest)) {
            return Result.error("请输入有效参数");
        }

        if (StringUtils.isEmpty(userLoginRequest.getEmail()) && StringUtils.isEmpty(userLoginRequest.getMobile())) {
            return Result.error("请输入手机号或邮箱");
        }

        if (StringUtils.isEmpty(userLoginRequest.getPassword())) {
            return Result.error("密码不能为空");
        }

        // 远程调用 根据邮箱或手机号查询用户信息
        UserInfoReq userInfoReq = new UserInfoReq();
        if (StringUtils.isNotEmpty(userLoginRequest.getEmail())) {
            userInfoReq.setEmail(userLoginRequest.getEmail());
            return gettUserResult(userLoginRequest, userInfoReq);
        }

        if (StringUtils.isNotEmpty(userLoginRequest.getMobile())) {
            userInfoReq.setMobile(userLoginRequest.getMobile());
            return gettUserResult(userLoginRequest, userInfoReq);
        }

        return Result.error("程序错误");
    }

    @NotNull
    private Result<TUser> gettUserResult(UserLoginRequest userLoginRequest, UserInfoReq userInfoReq) {
        TUser user;
        user = userLoginFeign.getUserInfo(userInfoReq).getData();
        if (ObjectUtil.isNull(user)) {
            return Result.error("该邮箱或手机号尚未注册");
        }

        if (ObjectUtil.isNull(user.getIsValid()) || user.getIsValid() == 1) {
            return Result.error("该用户已禁用");
        }

        String encode = passwordEncoder.encode(user.getPassword());
        String encode1 = passwordEncoder.encode(userLoginRequest.getPassword());
        if (!encode.equals(encode1)) {
            return Result.error("密码输入错误！");
        }

        return Result.success(user);
    }

    @Override
    public Result<JwtResponse> createToken(Result<TUser> userInfo) {
        // 生成key
        String userKey = UUID.randomUUID().toString().replace("-", "");

        Map<String, Object> map = new HashMap<>();
        map.put(JwtConstants.USER_KEY, userKey);
        map.put(JwtConstants.DETAILS_USER_ID, userInfo.getData().getId());
        map.put(JwtConstants.DETAILS_USERNAME, userInfo.getData().getNickname());

        // 生成token
        String token = JwtUtils.createToken(map);

        // 存入redis 并设置过期时间
        redisTemplate.opsForValue().set(JwtConstants.USER_KEY + userKey, userInfo, TokenConstants.EXPIRATION, TimeUnit.MINUTES);

        // 返回数据
        JwtResponse jwtResponse = new JwtResponse();
        jwtResponse.setToken(token);
        jwtResponse.setExpired(String.valueOf(TokenConstants.EXPIRATION));
        return Result.success(jwtResponse);
    }

    @Override
    public Result registered(UserRegisteredReq req) {
        // 参数校验
        if (ObjectUtil.isNull(req)) {
            return Result.error("请输入有效参数");
        }

        // 正则校验手机号
        String regex = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|(19[1,5,8,9]))\\d{8}$";
        if (!req.getMobile().matches(regex)) {
            return Result.error("手机号格式错误");
        }

        // 手机号唯一性校验
        UserInfoReq userInfoReq = new UserInfoReq();
        userInfoReq.setMobile(req.getMobile());
        TUser user = userLoginFeign.getUserInfo(userInfoReq).getData();

        if (ObjectUtil.isNotNull(user)) {
            return Result.error("该手机号已注册");
        }

        // 正则校验邮箱
        String regexEmail = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
        if (!req.getEmail().matches(regexEmail)) {
            return Result.error("邮箱格式错误");
        }

        // 密码强度校验
        String regexPassword = "^\\S*(?=\\S{6,})(?=\\S*\\d)(?=\\S*[A-Z])(?=\\S*[a-z])(?=\\S*[!@#$%^&*? ])\\S*$";
        if (!req.getPassword().matches(regexPassword)) {
            return Result.error("密码强度不够");
        }

        // 校验验证码
        Object o = redisTemplate.opsForValue().get(req.getMobile());
        if (ObjectUtil.isNull(o)) {
            return Result.error("验证码已过期");
        }

        String code = JSON.toJSONString(o);
        if (!code.equals(req.getCode())) {
            return Result.error("验证码错误");
        }

        // 删除redis验证码
        redisTemplate.delete(req.getMobile());

        // 密码使用encrypt进行密码加密
        req.setPassword(passwordEncoder.encode(req.getPassword()));

        // 存入数据库
        return userLoginFeign.save(req);
    }

    @Override
    public Result sendSms(String mobile) {
        if (StringUtils.isEmpty(mobile)) {
            return Result.error("请输入手机号");
        }

        // 生成6位纯数字验证码
        Random random = new Random();
        // 范围：100000 ~ 999999
        int codeInt = 100000 + random.nextInt(900000);
        String code = String.valueOf(codeInt);
        sendSmsUtils.sendSms(mobile, code);

        // 存入redis
        redisTemplate.opsForValue().set(mobile, code, 5, TimeUnit.MINUTES);

        return Result.success("发送成功");
    }

    @Override
    public Result send(String mobile) {
        if (StringUtils.isEmpty(mobile)) {
            return Result.error("请输入手机号");
        }

        UserInfoReq userInfoReq = new UserInfoReq();
        userInfoReq.setMobile(mobile);
        TUser user = userLoginFeign.getUserInfo(userInfoReq).getData();
        if (ObjectUtil.isNull(user)) {
            return Result.error("该手机号尚未注册");
        }

        // 生成6位纯数字验证码

        Random random = new Random();
        // 范围：100000 ~ 999999
        int codeInt = 100000 + random.nextInt(900000);
        String code = String.valueOf(codeInt);
        sendSmsUtils.sendSms(mobile, code);

        // 存入redis
        redisTemplate.opsForValue().set(mobile, code, 5, TimeUnit.MINUTES);
        return Result.success("发送成功");
    }

    @Override
    public Result forgetPassword(ForgetPasswordDto req) {
        if (ObjectUtil.isNull(req)) {
            return Result.error("请输入有效参数");
        }

        if (!req.getPassword().equals(req.getConfirmPassword())) {
            return Result.error("密码不一致");
        }

        req.setPassword(passwordEncoder.encode(req.getPassword()));

        // 存入数据库
        return userLoginFeign.forgetPassword(req);
    }
}
